﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Linq;
using Workbench.Models;
using Workbench.Persistance;
using Workbench.Presentation;
using Workbench.Shared;

namespace WorkbenchTests.ViewModels
{
    [TestClass]
    public class ConcordancerViewModelTests 
    {
        [TestInitialize]
        public void Setup()
        {
            TestUtility.CreateAndInitializeTempDatabase();
        }

        [TestCleanup]
        public void Teardown()
        {
            DBContext.Current.UnInitialize();
        }

        [TestMethod]
        public void ConcordancerViewModel_GetAdjacentWords()
        {
            var file = TestUtility.CreateProcessedFile("This is a simple text file.");
            var vm = new ConcordancerViewModel();

            vm.CurrentSearchContent = "a"; 
            TestUtility.DoEvents();

            var aWord = vm.SuggestedWords.Where(x => x.Content == "a").SingleOrDefault();
            Assert.IsNotNull(aWord);

            vm.SelectedWordSuggestion = aWord;

            Assert.AreEqual("is", vm.Words[0].LeftWord1);
            Assert.AreEqual("This", vm.Words[0].LeftWord2);

            Assert.AreEqual("simple", vm.Words[0].RightWord1);
            Assert.AreEqual("text", vm.Words[0].RightWord2);
            Assert.AreEqual("file", vm.Words[0].RightWord3);

            Assert.AreEqual("a", vm.Words[0].WordContent);
        }

        [TestMethod]
        public void ConcordancerViewModel_GetSuggestions()
        {
            var file = TestUtility.CreateProcessedFile("This is a simple text file.");
            var vm = new ConcordancerViewModel();

            vm.CurrentSearchContent = "This";
            vm.SuggestionType = SuggestionType.WordForm;
            TestUtility.DoEvents();
            Assert.AreEqual(1, vm.SuggestedWords.Count);
            Assert.AreEqual("This", vm.SuggestedWords[0].Content);

            vm.CurrentSearchContent = "text";
            TestUtility.DoEvents();
            vm.SuggestionType = SuggestionType.WordForm;
            Assert.AreEqual(1, vm.SuggestedWords.Count);
            Assert.AreEqual("text", vm.SuggestedWords[0].Content);

            TestUtility.LemmatizeWordsSameAsOriginalWordWithoutLastCharacter();

            vm.SuggestionType = SuggestionType.BaseForm;
            vm.CurrentSearchContent = "Thi";
            TestUtility.DoEvents();
            Assert.AreEqual(1, vm.SuggestedWords.Count);
            Assert.AreEqual("Thi", vm.SuggestedWords[0].Content);

            vm.SuggestionType = SuggestionType.BaseForm;
            vm.CurrentSearchContent = "tex";
            TestUtility.DoEvents();
            Assert.AreEqual(1, vm.SuggestedWords.Count);
            Assert.AreEqual("tex", vm.SuggestedWords[0].Content);
        }

        [TestMethod]
        public void ConcordancerViewModel_GetSuggestions_is_case_insensitive()
        {
            var file = TestUtility.CreateProcessedFile("This is a simple text file.");
            var vm = new ConcordancerViewModel();

            vm.CurrentSearchContent = "t";
            vm.SuggestionType = SuggestionType.WordForm;
            TestUtility.DoEvents();
            Assert.AreEqual(2, vm.SuggestedWords.Count);
            Assert.AreEqual("This", vm.SuggestedWords[0].Content);
            Assert.AreEqual("text", vm.SuggestedWords[1].Content);
        }

        [TestMethod]
        public void ConcordancerViewModel_cant_go_up_or_down_by_more_than_five()
        {
            var vm = new ConcordancerViewModel();
            vm.SortingColumn = 0;
            if (vm.UpCommand.CanExecute(null)) vm.UpCommand.Execute(null);
            Assert.AreEqual(1, vm.SortingColumn);

            if (vm.UpCommand.CanExecute(null)) vm.UpCommand.Execute(null);
            Assert.AreEqual(2, vm.SortingColumn);

            if (vm.UpCommand.CanExecute(null)) vm.UpCommand.Execute(null);
            Assert.AreEqual(3, vm.SortingColumn);

            if (vm.UpCommand.CanExecute(null)) vm.UpCommand.Execute(null);
            Assert.AreEqual(4, vm.SortingColumn);

            if (vm.UpCommand.CanExecute(null)) vm.UpCommand.Execute(null);
            Assert.AreEqual(5, vm.SortingColumn);

            if (vm.DownCommand.CanExecute(null)) vm.DownCommand.Execute(null);
            Assert.AreEqual(4, vm.SortingColumn);

            vm.SortingColumn = 0;

            if (vm.DownCommand.CanExecute(null)) vm.DownCommand.Execute(null);
            Assert.AreEqual(-1, vm.SortingColumn);

            if (vm.DownCommand.CanExecute(null)) vm.DownCommand.Execute(null);
            Assert.AreEqual(-2, vm.SortingColumn);

            if (vm.DownCommand.CanExecute(null)) vm.DownCommand.Execute(null);
            Assert.AreEqual(-3, vm.SortingColumn);

            if (vm.DownCommand.CanExecute(null)) vm.DownCommand.Execute(null);
            Assert.AreEqual(-4, vm.SortingColumn);

            if (vm.DownCommand.CanExecute(null)) vm.DownCommand.Execute(null);
            Assert.AreEqual(-5, vm.SortingColumn);
        }
        
        [TestMethod]
        public void ConcordancerViewModel_can_sort_by_column_alphabetically()
        {
            var vm = new ConcordancerViewModel();
            var wordsWithNearWords = new List<WordWithNearWordsModel>()
            {
                new WordWithNearWordsModel() { 
                    Word = "A", 
                    WordsToTheLeft = new List<string>() { "B", "C", "D", "E" }, 
                    WordsToTheRight = new List<string>() { "B", "C", "D", "E"} 
                }, new WordWithNearWordsModel() { 
                    Word = "A", 
                    WordsToTheLeft = new List<string>() { "C", "B", "E", "D" }, 
                    WordsToTheRight = new List<string>() { "C", "B", "E", "D"} 
                }
            
            };
            vm.Words.AddRange(wordsWithNearWords.Select(x => new WordWithNearWordsViewModel(x)));

            vm.SortingType = ConcordancerSortingType.Alphabetically;
            vm.SortingColumn = 1;
            Assert.IsTrue(vm.SortCommand.CanExecute(null));
            vm.SortCommand.Execute(null);

            Assert.AreEqual("B", vm.Words[0].RightWord1);
            Assert.AreEqual("C", vm.Words[1].RightWord1);

            vm.SortingColumn = 2;
            Assert.IsTrue(vm.SortCommand.CanExecute(null));
            vm.SortCommand.Execute(null);

            Assert.AreEqual("B", vm.Words[0].RightWord2);
            Assert.AreEqual("C", vm.Words[1].RightWord2);

            vm.SortingColumn = 3;
            Assert.IsTrue(vm.SortCommand.CanExecute(null));
            vm.SortCommand.Execute(null);

            Assert.AreEqual("D", vm.Words[0].RightWord3);
            Assert.AreEqual("E", vm.Words[1].RightWord3);

            vm.SortingColumn = 4;
            Assert.IsTrue(vm.SortCommand.CanExecute(null));
            vm.SortCommand.Execute(null);

            Assert.AreEqual("D", vm.Words[0].RightWord4);
            Assert.AreEqual("E", vm.Words[1].RightWord4);

            vm.SortingColumn = 5;
            Assert.IsFalse(vm.SortCommand.CanExecute(null));


            vm.SortingColumn = -1;
            Assert.IsTrue(vm.SortCommand.CanExecute(null));
            vm.SortCommand.Execute(null);

            Assert.AreEqual("B", vm.Words[0].LeftWord1);
            Assert.AreEqual("C", vm.Words[1].LeftWord1);

            vm.SortingColumn = -2;
            Assert.IsTrue(vm.SortCommand.CanExecute(null));
            vm.SortCommand.Execute(null);

            Assert.AreEqual("B", vm.Words[0].LeftWord2);
            Assert.AreEqual("C", vm.Words[1].LeftWord2);

            vm.SortingColumn = -3;
            Assert.IsTrue(vm.SortCommand.CanExecute(null));
            vm.SortCommand.Execute(null);

            Assert.AreEqual("D", vm.Words[0].LeftWord3);
            Assert.AreEqual("E", vm.Words[1].LeftWord3);

            vm.SortingColumn = -4;
            Assert.IsTrue(vm.SortCommand.CanExecute(null));
            vm.SortCommand.Execute(null);

            Assert.AreEqual("D", vm.Words[0].LeftWord4);
            Assert.AreEqual("E", vm.Words[1].LeftWord4);

            vm.SortingColumn = -5;
            Assert.IsFalse(vm.SortCommand.CanExecute(null));
        }

        [TestMethod]
        public void ConcordancerViewModel_can_sort_by_column_by_frequency()
        {
            var vm = new ConcordancerViewModel();
            var wordsWithNearWords = new List<WordWithNearWordsModel>()
            {
                new WordWithNearWordsModel() { 
                    Word = "A", 
                    WordsToTheLeft = new List<string>() { "B", "C", "D", "E" }, 
                    WordsToTheRight = new List<string>() { "B", "C", "D", "E"} 
                }, new WordWithNearWordsModel() { 
                    Word = "A", 
                    WordsToTheLeft = new List<string>() { "C", "B", "E", "D" }, 
                    WordsToTheRight = new List<string>() { "C", "B", "E", "D"} 
                }, new WordWithNearWordsModel() { 
                    Word = "A", 
                    WordsToTheLeft = new List<string>() { "C", "B", "E", "D" }, 
                    WordsToTheRight = new List<string>() { "C", "B", "E", "D"} 
                }
            
            };
            vm.Words.AddRange(wordsWithNearWords.Select(x => new WordWithNearWordsViewModel(x)));

            vm.SortingType = ConcordancerSortingType.Frequency;
            vm.SortingColumn = 1;
            Assert.IsTrue(vm.SortCommand.CanExecute(null));
            vm.SortCommand.Execute(null);

            Assert.AreEqual("C", vm.Words[0].RightWord1);
            Assert.AreEqual("C", vm.Words[1].RightWord1);
            Assert.AreEqual("B", vm.Words[2].RightWord1);

            vm.SortingColumn = 2;
            Assert.IsTrue(vm.SortCommand.CanExecute(null));
            vm.SortCommand.Execute(null);

            Assert.AreEqual("B", vm.Words[0].RightWord2);
            Assert.AreEqual("B", vm.Words[1].RightWord2);
            Assert.AreEqual("C", vm.Words[2].RightWord2);

            vm.SortingColumn = 3;
            Assert.IsTrue(vm.SortCommand.CanExecute(null));
            vm.SortCommand.Execute(null);

            Assert.AreEqual("E", vm.Words[0].RightWord3);
            Assert.AreEqual("E", vm.Words[1].RightWord3);
            Assert.AreEqual("D", vm.Words[2].RightWord3);

            vm.SortingColumn = 4;
            Assert.IsTrue(vm.SortCommand.CanExecute(null));
            vm.SortCommand.Execute(null);

            Assert.AreEqual("D", vm.Words[0].RightWord4);
            Assert.AreEqual("D", vm.Words[1].RightWord4);
            Assert.AreEqual("E", vm.Words[2].RightWord4);

            vm.SortingColumn = 5;
            Assert.IsFalse(vm.SortCommand.CanExecute(null));


            vm.SortingColumn = -1;
            Assert.IsTrue(vm.SortCommand.CanExecute(null));
            vm.SortCommand.Execute(null);

            Assert.AreEqual("C", vm.Words[0].LeftWord1);
            Assert.AreEqual("C", vm.Words[1].LeftWord1);
            Assert.AreEqual("B", vm.Words[2].LeftWord1);

            vm.SortingColumn = -2;
            Assert.IsTrue(vm.SortCommand.CanExecute(null));
            vm.SortCommand.Execute(null);

            Assert.AreEqual("B", vm.Words[0].LeftWord2);
            Assert.AreEqual("B", vm.Words[1].LeftWord2);
            Assert.AreEqual("C", vm.Words[2].LeftWord2);

            vm.SortingColumn = -3;
            Assert.IsTrue(vm.SortCommand.CanExecute(null));
            vm.SortCommand.Execute(null);

            Assert.AreEqual("E", vm.Words[0].LeftWord3);
            Assert.AreEqual("E", vm.Words[1].LeftWord3);
            Assert.AreEqual("D", vm.Words[2].LeftWord3);

            vm.SortingColumn = -4;
            Assert.IsTrue(vm.SortCommand.CanExecute(null));
            vm.SortCommand.Execute(null);

            Assert.AreEqual("D", vm.Words[0].LeftWord4);
            Assert.AreEqual("D", vm.Words[1].LeftWord4);
            Assert.AreEqual("E", vm.Words[2].LeftWord4);

            vm.SortingColumn = -5;
            Assert.IsFalse(vm.SortCommand.CanExecute(null));
        }
    }
}
